﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using System.Xml.Linq;
using NetAcademia.Web.Mvc;
using System.IO;

namespace HtmlLaundryTests
{
    [TestClass]
    public class XSSTestsWithDefaultWhitelist  //from http://ha.ckers.org/xss.html
    {
        string whitelist;

        [TestInitialize]
        public void LoadWhitelist()
        {
            StreamReader sr = new StreamReader(@"D:\Projects\HtmlLaundry\HtmlLaundryTests\default.whitelist");
            this.whitelist = sr.ReadToEnd();
        }

        [TestMethod]
        public void XssLocator()
        {
           
            string html = @"';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//"";alert(String.fromCharCode(88,83,83))//\"";alert(String.fromCharCode(88,83,83))//--></SCRIPT>"">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>";
            string accepted = @"';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//"";alert(String.fromCharCode(88,83,83))//\"";alert(String.fromCharCode(88,83,83))//--&gt;""&gt;'&gt;alert(String.fromCharCode(88,83,83))";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void XssLocator2()
        {

            string html = @"'';!--""<XSS>=&{()}";
            string accepted = @"'';!--""=&amp;{()}";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void NoFilterEvasion()
        {
            string html = @"<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>";
            string accepted = @"";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXss()
        {
            string html = @"<IMG SRC=""javascript:alert('XSS');"">";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssNoQuotesNoSemicolon()
        {
            string html = @"<IMG SRC=javascript:alert('XSS')>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssCaseInsensitive()
        {
            string html = @"<IMG SRC=JaVaScRiPt:alert('XSS')>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssEncodedHtml()
        {
            string html = @"<IMG SRC=javascript:alert(&quot;XSS&quot;)>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssGraveAccentObfuscation()
        {
            string html = @"<IMG SRC=`javascript:alert(""RSnake says, 'XSS'"")`>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssMalformadImg()
        {
            string html = @"<IMG """"""><SCRIPT>alert(""XSS"")</SCRIPT>"">";
            string accepted = @"<img>alert(""XSS"")""&gt;</img>";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssFromCharCode()
        {
            string html = @"<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssUtf8Encoding()
        {
            string html = @"<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssHexEncoding()
        {
            string html = @"<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssEmbeddedTab()
        {
            string html = @"<IMG SRC=""jav	ascript:alert('XSS');"">";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssEmbeddedEncodedTab()
        {
            string html = @"<IMG SRC=""jav&#x0A;ascript:alert('XSS');"">";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssEmbeddedEncodedNewLine()
        {
            string html = @"<IMG SRC=""jav&#x0A;ascript:alert('XSS');"">";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssEmbeddedEncodedCarrigeReturn()
        {
            string html = @"<IMG SRC=""jav&#x0D;ascript:alert('XSS');"">";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ImageXssMultiline()
        {
            string html = @"<IMG
SRC
=
""
j
a
v
a
s
c
r
i
p
t
:
a
l
e
r
t
(
'
X
S
S
'
)
""
>
";
            string accepted = @"<img>
</img>";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        //IMG SRC=java\0script:alert(\"XSS\")>

        [TestMethod]
        public void ImageXssNullChar()
        {
            string html = @"<IMG SRC=java\0script:alert(\""XSS\"")>";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void ScriptTagNullChar()
        {
            string html = @"<SCR\0IPT>alert(\""XSS\"")</SCR\0IPT>";
            string accepted = @"alert(\""XSS\"")&lt;/SCR\0IPT&gt;";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        //Spaces and meta chars before the JavaScript in images for XSS (
        [TestMethod]
        public void ImageXssPreSpaced()
        {
            string html = @"<IMG SRC="" &#14;  javascript:alert('XSS');"">";
            string accepted = @"<img />";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void NonAlphaNonDigit()
        {
            string html = @"<SCRIPT/XSS SRC=""http://ha.ckers.org/xss.js""></SCRIPT>";
            string accepted = @"";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void NonAlphaNonDigit2()
        {
            string html = @"<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert(""XSS"")>";
            string accepted = @"";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void NonAlphaNonDigit3()
        {
            string html = @"<SCRIPT/SRC=""http://ha.ckers.org/xss.js""></SCRIPT>";
            string accepted = @"";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void ExtraOpenBrackets()
        {
            string html = @"<<SCRIPT>alert(""XSS"");//<</SCRIPT>";
            string accepted = @"&lt;alert(""XSS"");//&lt;";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void NoClosing()
        {
            string html = @"<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>";
            string accepted = @"";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }

        [TestMethod]
        public void ProtocolResolution()
        {
            string html = @"<SCRIPT SRC=//ha.ckers.org/.j>";
            string accepted = @"";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }




        [TestMethod]
        public void JavascriptLink()
        {
            string html = @"<A HREF=""javascript:document.location='http://www.google.com/'"">XSS</A>";
            string accepted = @"<a>XSS</a>";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }


        [TestMethod]
        public void ContentReplaceAttack()
        {
            string html = @"<A HREF=""http://www.gohttp://www.google.com/ogle.com/"">XSS</A>";
            string accepted = @"<a>XSS</a>";

            HtmlLaundry machine = new HtmlLaundry(whitelist);

            string outcome = machine.CleanHtml(html);

            Assert.AreEqual(accepted, outcome);
        }
    }
}
